#pragma once

/// <summary>
/// Asset Manager: Responsible for storing and accessing material, model and instance data
/// </summary>

/**
  * Author: Michael Leviston
  * Created: 14/06/13
  * Last Modified: 29/06/13
  * Version: v1.0
  */

// Includes
#include <map>
#include <string>

#include "BasicMesh.h"
#include "InstanceMap.h"
#include "ModelData.h"
#include "GeometryFactory.h"

// Class Definition
class AssetManager
{
public:
//==============================
// Constructors / Destructors
//==============================

	/// Default Constructor
	AssetManager();

	/// Default Destructor
	~AssetManager();

//==============================
// Initialisation Methods
//==============================

	/**
	  * Initialise the Asset Manager instance
	  *
      * Initialiser that stores a pointer to the D3D Device
	  * @param Pointer to D3D Device
	  */
	void Initialise(ID3D11Device* md3dDevice);

	/// InitMaterials - Initialise default mesh materials for use with basic meshes
	void InitMaterials();

	/// InitMeshes - Initialise default meshes, adding instance map and model data to relevant member containers
	void InitMeshes();

//==============================
// Player Mesh Methods
//==============================

	/**
	  * Create the player model vertex buffers
	  *
      * CreatePlayerVertexBuffer
	  * @param  Pointer to D3D Device
	  * @return Pointer to vertex buffer storing player cylinder vertices
	  */
	ID3D11Buffer* CreatePlayerVertexBuffer(ID3D11Device* md3dDevice);

	/**
	  * Create the player model index buffers
	  *
      * CreatePlayerIndexBuffer
	  * @param  Pointer to D3D Device
	  * @return Pointer to index buffer storing player cylinder indices
	  */
	ID3D11Buffer* CreatePlayerIndexBuffer(ID3D11Device* md3dDevice);


//==============================
// Add to Container Methods
//==============================

   /**
	 * Add a material to the map of materials
	 *
     * AddMaterial - Stores a material in m_mapMaterials
	 * @param Unique name of material
	 * @param Material& with description of material
	 */
	void AddMaterial(std::string name, Material& material);

   /**
	 * Add a model to the map of models
	 *
     * AddModel- Stores a model in m_mapModels
	 * @param Unique name of model
	 * @param ModelData* with description of model
	 */
	void AddModel(std::string Name, ModelData* Model);

   /**
	 * Add an instance map to the map of instance maps
	 *
     * AddInstanceMap - Stores an Instance Map in m_mapInstances
	 * @param Unique name of instances
	 * @param InstanceMap* with description of instances
	 */
	void AddInstanceMap(std::string name, InstanceMap* instanceMap);

   /**
	 * Add a basic mesh to the vector of basic meshes
	 *
     * AddBasicMesh
	 * @param Vertex buffer of mesh
	 * @param Index buffer of mesh
	 * @param Name of mesh material
	 */
	void AddBasicMesh(ID3D11Buffer* vb, ID3D11Buffer* ib, std::string material);

//==============================
// Get from Container Methods
//==============================

   /**
   	 * Get a pointer to a stored material
	 *
     * GetMaterial
	 * @param  Name of material to retrieve
	 * @return Pointer to the material requested
	 */
	Material*		GetMaterial(std::string material);

   /**
   	 * Get a pointer to a stored instance map
	 *
     * GetInstanceMap
	 * @param  Name of instance map to retrieve
	 * @return Pointer to the instance map requested
	 */
	InstanceMap*	GetInstanceMap(std::string name);

   /**
   	 * Get a pointer to stored model data
	 *
     * GetModelData
	 * @param  Name of model data to retrieve
	 * @return Pointer to the model data requested
	 */
	ModelData*		GetModelData(std::string name);

   /**
   	 * Get a pointer to the stored basic meshes
	 *
     * GetBasicMeshes
	 * @return Pointer to the vector containing all basic meshes (m_vecMeshes)
	 */
	std::vector<IMesh*>* GetBasicMeshes();

   /**
   	 * Create a vector of all of the instance map pointers
	 *
     * GetInstanceMaps
	 * @param Vector of InstanceMap Pointers to which the stored instance map pointers will be added
	 */
	void GetInstanceMaps(std::vector<InstanceMap*>& vecInstanceMaps);

   /**
   	 * Create a vector of all of the model data pointers
	 *
     * GetModelData
	 * @param Vector of ModelData Pointers to which the stored model data pointers will be added
	 */
	void GetModelData(std::vector<ModelData*>& vecModelData);

//==============================
// Shutdown Methods
//==============================

	/// Shutdown - Release and Delete Resources
	void Shutdown();

	/// DeleteAssets - Loops through all containers calling shutdown and deletion methods on stored data
	void DeleteAssets();

private:

	ID3D11Device*	 m_d3dDevice;		///< Pointer to D3D Device
	GeometryFactory* m_GeoFactory;		///< Geometry Factory Helper

	std::vector<IMesh*>					m_vecMeshes;		///< Store Basic Meshes e.g. floor mesh
	std::map<std::string, Material>		m_mapMaterials;		///< Store Materals
	std::map<std::string, InstanceMap*> m_mapInstances;		///< Store Instance Maps
	std::map<std::string, ModelData*>	m_mapModels;		///< Store Model Data

};